using Godot;
using System;
using System.Collections.Generic;

public partial class AudioManager : Node
{
    // 单例模式，方便全局调用
    public static AudioManager Instance { get; private set; }

    // 配置
    private const int InitialPoolSize = 12; // 初始12个音效播放器
    private const string MusicBus = "Music";
    private const string SfxBus = "SFX";

    // 组件
    private AudioStreamPlayer _musicPlayer;
    private List<AudioStreamPlayer> _sfxPool;

    // 资源缓存：路径 -> 音频资源 (防止重复加载)
    private Dictionary<string, AudioStream> _audioCache = new();

    public override void _Ready()
    {
        Instance = this;

        // 1. 初始化背景音乐播放器
        _musicPlayer = new AudioStreamPlayer();
        _musicPlayer.Bus = MusicBus;
        AddChild(_musicPlayer);

        // 2. 初始化音效对象池
        _sfxPool = new List<AudioStreamPlayer>();
        for (int i = 0; i < InitialPoolSize; i++)
        {
            CreateNewSfxPlayer();
        }

        GD.Print("AudioManager 初始化完成");
    }

    // --- 核心功能 1: 播放背景音乐 (支持淡入淡出) ---
    public void PlayMusic(string path, float fadeDuration = 1.0f)
    {
        var stream = LoadAudio(path);
        if (stream == null)
        {
            GD.PrintErr($"无法播放音乐，加载失败: {path}");
            return;
        }

        // 如果当前已经在放这首，就不重置了
        if (_musicPlayer.Stream == stream && _musicPlayer.Playing) return;

        // 使用 Tween 实现淡出淡入
        // Godot 4 的 Tween 非常好用
        Tween tween = CreateTween();

        if (_musicPlayer.Playing)
        {
            // 先淡出当前音乐
            tween.TweenProperty(_musicPlayer, "volume_db", -80.0f, fadeDuration / 2);
            tween.TweenCallback(Callable.From(() =>
            {
                _musicPlayer.Stream = stream;
                _musicPlayer.Play();
            }));
        }
        else
        {
            // 直接设置
            _musicPlayer.Stream = stream;
            _musicPlayer.VolumeDb = -80.0f; // 从静音开始
            _musicPlayer.Play();
        }

        // 淡入新音乐
        // 注意：这里假设正常音量是 0db。如果你的素材声音大，可以设为 -5 或 -10
        tween.TweenProperty(_musicPlayer, "volume_db", 0.0f, fadeDuration / 2);
    }


    public void PlayMusicLoop(string path, float fade_out_in_Duration = 1.0f)
    {

    }



    // --- 核心功能 2: 播放音效 (高性能对象池) ---
    // path: 路径
    // pitchVariance: 音调随机范围 (比如 0.1 代表 0.9~1.1)
    public void PlaySfx(string path, float volumeDb = 0f, float pitchVariance = 0f)
    {
        var stream = LoadAudio(path);
        if (stream == null) return;

        // 1. 从池子里找一个没在干活的播放器
        AudioStreamPlayer player = GetAvailablePlayer();

        // 2. 设置属性
        player.Stream = stream;
        player.VolumeDb = volumeDb;

        if (pitchVariance > 0)
        {
            player.PitchScale = (float)GD.RandRange(1.0f - pitchVariance, 1.0f + pitchVariance);
        }
        else
        {
            player.PitchScale = 1.0f;
        }

        // 3. 播放
        player.Play();
    }

    // --- 辅助方法 ---

    private AudioStreamPlayer GetAvailablePlayer()
    {
        foreach (var player in _sfxPool)
        {
            if (!player.Playing)
            {
                return player;
            }
        }

        // 如果池子里的都忙着，就扩容创建一个新的
        return CreateNewSfxPlayer();
    }

    private AudioStreamPlayer CreateNewSfxPlayer()
    {
        var p = new AudioStreamPlayer();
        p.Bus = SfxBus;
        AddChild(p);
        _sfxPool.Add(p);
        return p;
    }

    // 资源加载与缓存
    private AudioStream LoadAudio(string path)
    {
        if (_audioCache.ContainsKey(path))
        {
            return _audioCache[path];
        }

        if (!ResourceLoader.Exists(path))
        {
            GD.PrintErr($"音频文件未找到: {path}");
            return null;
        }

        var stream = GD.Load<AudioStream>(path);
        _audioCache[path] = stream; // 存入缓存
        return stream;
    }



    public void StopMusic(float fadeDuration = 0f)
    {
        if (_musicPlayer.Playing)
        {
            Tween tween = CreateTween();
            tween.TweenProperty(_musicPlayer, "volume_db", -80.0f, fadeDuration);
            tween.TweenCallback(Callable.From(() =>
            {
                _musicPlayer.Stop();
                _musicPlayer.Stream = null;
            }));
        }
    }
}